<?php

//爬虫 类
class spdier
{
    /**
     * @var object 请求管道对象
     */
    private $request_chan;

    /**
     * @var object 解析HTML管道对象
     */
    private $analysis_chan;

    /**
     * @var object 下载文件管道对象
     */
    private $download_chan;
    /**
     * @var int 启动协程数量
     */
    private $coroutine_number = 10;
    /**
     * @var string 文件下载目录
     */
    private $download_dir;

    // 初始化爬虫类型
    public function __construct($url, $coroutine_number = 10, $dir = __DIR__)
    {
        ini_set('memory_limit', '1280M');
        $this->coroutine_number = $coroutine_number;
        if (!is_dir($dir)) { //检查保存目录是否存在
            mkdir($dir);  //不存在就创建
        }
        $this->download_dir = $dir;
        //实例化管道对象
        $this->request_chan = new Chan(300);
        //实例化管道对象
        $this->analysis_chan = new Chan(300);
        //实例化管道对象
        $this->download_chan = new Chan(300);
        //初始化任务投递
        go(function () use ($url) {
            $this->request_chan->push($url);
        });
    }

    /**
     * 执行
     */
    public function run()
    {
        foreach (range(1, $this->coroutine_number) as $v) {
            // 请求
            go(function () {
                while (true) {
                    $request_url = $this->request_chan->pop();
                    if (empty($request_url)) {
                        Co::sleep(0.1);
                    } else {
                        $html = $this->get(parse_url($request_url));
                        $this->analysis_chan->push($html);
                    }
                }
            });
            //解析
            go(function () {
                while (true) {
                    $html = $this->analysis_chan->pop();
                    if (empty($html)) {
                        Co::sleep(0.1);
                    } else {
                        $this->analysisHtml($html);
                    }
                }
            });
            //下载
            go(function () {
                while (true) {
                    $download_url = $this->download_chan->pop();
                    if (empty($download_url)) {
                        Co::sleep(0.1);
                    } else {
                        $this->download(parse_url($download_url), $this->download_dir);
                    }
                }
            });
        }
    }

    /**
     * @param string $html
     * 解析HTML  并区分请求 文件 投递
     */
    private function analysisHtml(string $html)
    {
        preg_match_all('/app.page\["pins"\] = (\[.+\])/', $html, $res);
        if (isset($res[1][0])) {
            $res = json_decode($res[1][0], true);
            $pin_id = 0;
            foreach ($res as $k => $v) {
                $images_url = 'https://hbimg.huabanimg.com/' . $v['file']['key'];
                $this->download_chan->push($images_url);
                $pin_id = $v['pin_id'];
            }
            $request_url = 'https://huaban.com/partner/uc/aimeinv/pins/?max=' . $pin_id . '&limit=8&wfl=1';
            $this->request_chan->push($request_url);
        }else{
            echo '数据没有了,', PHP_EOL;
            Co::sleep(2);
        }
    }


    /**
     * get请求
     * @param array $requestUrl [scheme=>,host=>,'path'=>]
     * @return string
     */
    private function get(array $requestUrl)
    {
        $ssl = $requestUrl['scheme'] === 'https' ? true : false;
        $port = $ssl ? 443 : 80;
        $cli = new \Swoole\Coroutine\Http\Client($requestUrl['host'], $port, $ssl);
        $cli->setHeaders([
            'Host' => $requestUrl['host'],
            "User-Agent" => 'Chrome/49.0.2587.3',
            'Accept' => 'text/html,application/xhtml+xml,application/xml',
            'Accept-Encoding' => 'gzip',
        ]);
        if (isset($requestUrl['query'])) {
            $requestUrl['path'] = $requestUrl['path'] . '?' . $requestUrl['query'];
        }
        $cli->get($requestUrl['path']);
        $res = $cli->body;
        $cli->close();
        return $res;
    }


    /**
     * @param $downloadUrl
     * @param $dir string 保存文件地址
     * 下载
     */
    private function download($downloadUrl, $dir)
    {
        $ssl = $downloadUrl['scheme'] === 'https' ? true : false;
        $port = $ssl ? 443 : 80;
        $cli = new \Swoole\Coroutine\Http\Client($downloadUrl['host'], $port, $ssl);
        $cli->download($downloadUrl['path'], $dir . $downloadUrl['path'] . '.png');
    }


}

$dir = __DIR__ . '/images/';
$spdier = new spdier('https://huaban.com/partner/uc/aimeinv/pins/', 10, $dir);
$spdier->run();


